
public class Board
{
	//global vars
	private int p_board[][];
	
	/**
	 * constructor initializes a 9x9 ArrayMatrix forming the
	 * board, instantiates a TileSet, and places the middle
	 * tile to start the game.
	 */
	public Board(int tile)
	{
		p_board = new int[9][9];
                p_board[4][4] = tile;
	}
	
	/**
	 * method placeTile is the public method which checks
	 * all of the needed things, such as valid placement
	 * and scoring and returns an integer of some sort.
	 * @param int row of p_board
	 * @param int col of p_board
	 * @param int value of tile played
	 * @return true if move is valid, false if not.
	 */
	public int placeTile(int row, int col, int tilePlayed)
	{
		int scoreTotal = 0;
		int totalScoreHorizVert = 0;
		int totalScoreDiagonal = 0;
		boolean doubleIt = checkDouble(row, col);
		
		totalScoreHorizVert = checkHorizVert(row, col, tilePlayed);
		totalScoreDiagonal = checkDiagonal(row, col, tilePlayed);
		
		scoreTotal = totalScoreHorizVert + totalScoreDiagonal;
		
		if(doubleIt)
		{
			scoreTotal = scoreTotal * 2;
		}
		
		if(totalScoreHorizVert == -1 || totalScoreDiagonal == -1)
		{
			p_board[row][col] = 0;
			scoreTotal = -1;
		}
		
		return scoreTotal;
	}
	
	/**
	 * checkHorizVert checks valid play on the up/down, left/right direction
	 * @param row of p_board
	 * @param col of p_board
	 * @param value of played tile
	 * @return -1 for invalid play or the score total for both vertical and 
	 * horizontal columns
	 */
	private int checkHorizVert(int row, int col, int tilePlayed)
	{
		int[] workingRow = new int[9];
		int[] workingCol = new int[9];
		int rowTotal = tilePlayed;
		int colTotal = tilePlayed;
		int totalRowColScore = 0;
		int sameNumRow = 1;
		int sameNumCol = 1;
		int backward = col;
		int forward = col;
		int up = row;
		int down = row;
		int runTotalDescCol = 0; 
		int runTotalDescRow = 0; 
		int runTotalAscCol = 0;
		int runTotalAscRow = 0;
		
		for(int i = 0; i < 9; i++)
		{
			workingCol[i] = p_board[i][col];
			System.out.print("row " + i + " col " + col);
			workingRow[i] = p_board[row][i];
			System.out.println(workingRow[i]);
		}
		
		workingCol[row] = tilePlayed;
		workingRow[col] = tilePlayed;
		
		while(workingRow[backward - 1] != 0 && workingRow[backward - 1] != -1)
		{
			backward--;
			rowTotal += workingRow[backward];
			if(workingRow[backward] == tilePlayed)
			{
				sameNumRow++;
			}
		}
		while(workingRow[forward + 1] != 0 && workingRow[forward + 1] != -1)
		{
			forward++;
			rowTotal += workingRow[forward];
			if(workingRow[forward] == tilePlayed)
			{
				sameNumRow++;
			}
		}
		
		while(workingCol[up - 1] != 0 && workingCol[up - 1] != -1)
		{
			up--;
			colTotal += workingCol[up];
			if(workingCol[up] == tilePlayed)
			{
				sameNumCol++;
			}
		}
		while(workingCol[down + 1] != 0 && workingCol[down + 1] != -1)
		{
			down++;
			colTotal += workingCol[down];
			if(workingCol[down] == tilePlayed)
			{
				sameNumCol++;
			}
		}
		 
		// scoring block for everything
		
		if(rowTotal <= 24 && colTotal <= 24) //only score if not bust.
		{
			p_board[row][col] = tilePlayed; //play is legal, so place tile.
			
			
			//checks the runs ascending or descending.
			runTotalDescCol = testRunsDown(workingCol, row); 
			runTotalDescRow = testRunsDown(workingRow, col);
			runTotalAscCol =  testRunsUp(workingCol, row);
			runTotalAscRow = testRunsUp(workingRow, col);
			
			if(rowTotal == 24)
			{
				setNoPlayMarkersHV(row, col);
			}
			
			if(colTotal == 24)
			{
				setNoPlayMarkersHV(row, col);
			}

			System.out.println("rowTotal is: " + rowTotal);
			if(rowTotal == 7 && tilePlayed !=7)
			{
				totalRowColScore += 20;
			}
			if(colTotal == 7 && tilePlayed != 7)
			{
				totalRowColScore += 20;
			}
			//scores if the total in the row is 7 or 24
			switch(rowTotal)
			{
				case 24: totalRowColScore += 40;  break;
			}
			System.out.println("colTotal is: " + colTotal); 
			switch(colTotal)
			{
				case 24: totalRowColScore += 40;  break;
			}
			
			System.out.println("sameNumRow is: " + sameNumRow);
			//scores 3/4-of-kind
			switch(sameNumRow)
			{
				case 3:  totalRowColScore += 50;  break;
				case 4:  totalRowColScore += 60;  break;
			}
			
			System.out.println("sameNumCol is: " + sameNumCol);
			switch(sameNumCol)
			{
				case 3:  totalRowColScore += 50;  break;
				case 4:  totalRowColScore += 60;  break;
			}
			System.out.println("Sum of runTotalDescColis: " + runTotalDescCol);
			// scores runs, both descending and ascending
			switch(runTotalDescCol)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
			
			System.out.println("Sum of runTotalAscCol is: " + runTotalAscCol);
			// scores runs, both descending and ascending
			switch(runTotalDescCol)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
			
			System.out.println("Sum of runTotalDescRow is: " + runTotalDescRow);
			switch(runTotalDescRow)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
			System.out.println("Sum of runTotalAsccRow is: " + runTotalAscRow);
			switch(runTotalAscRow)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
		}
		
		else if(rowTotal > 24 || colTotal > 24)
		{
			totalRowColScore = -1;
		}
		
		System.out.println("The total for Horiz/Vert is: " + totalRowColScore);
		return totalRowColScore;
	}
	
	/**
	 * 
	 * @param row of p_board
	 * @param col of p_board
	 * @param value of tile played
	 * @return -1 for invalid play, total score of the diagonals otherwise.
	 */
	private int checkDiagonal(int row, int col, int tilePlayed)
	{
		int[] workingRowDiag = new int[9];
		int[] workingColDiag = new int[9];
		int rowTotal = tilePlayed;
		int colTotal = tilePlayed;
		int totalRowColScore = 0;
		int sameNumRow = 1;
		int sameNumCol = 1;
		int backward = col;
		int forward = col;
		int up = row;
		int down = row;
		int runTotalDescCol = 0; 
		int runTotalDescRow = 0; 
		int runTotalAscCol = 0;
		int runTotalAscRow = 0;
		
		int diagUpLeftRow = row;
		int diagUpLeftCol = col;
		int diagDownRightRow = row;
		int diagDownRightCol = col;
		int diagUpRightRow = row;
		int diagUpRightCol = col;
		int diagDownLeftRow = row;
		int diagDownLeftCol = col;
		
		for(int i = 0; i < 9; i++)
		{
			workingRowDiag[i] = 0;
			workingColDiag[i] = 0;
		}
		

		workingRowDiag[col] = tilePlayed; 
		workingColDiag[row] = tilePlayed;
		
		while(diagUpLeftRow != 0 && diagUpLeftCol != 0)
		{
			diagUpLeftRow--;
			diagUpLeftCol--;
			workingRowDiag[diagUpLeftCol] = p_board[diagUpLeftRow][diagUpLeftCol];
		}
		
		while(diagDownRightRow != 8 && diagDownRightCol != 8)
		{
			diagDownRightRow++;
			diagDownRightCol++;
			workingRowDiag[diagDownRightCol] = p_board[diagDownRightRow][diagDownRightCol];
		}
		
				
		while(diagDownLeftRow != 8 && diagDownLeftCol != 0)
		{
			diagDownLeftRow++;
			diagDownLeftCol--;
			workingColDiag[diagDownLeftCol] = p_board[diagDownLeftRow][diagDownLeftCol];
		}
		
		while(diagUpRightRow != 0 && diagUpRightCol != 8)
		{
			diagUpRightRow--;
			diagUpRightCol++;
			workingColDiag[diagUpRightCol] = p_board[diagUpRightRow][diagUpRightCol];
		}

		
		
		//large while block that builds the data for abridged arrays
		//and three/four-of-kind and 24/7 totals.
		while(workingRowDiag[backward - 1] != 0 && workingRowDiag[backward - 1] != -1)
		{
			backward--;
			rowTotal += workingRowDiag[backward];
			if(workingRowDiag[backward] == tilePlayed)
			{
				sameNumRow++;
			}
		}
		while(workingRowDiag[forward + 1] != 0 && workingRowDiag[forward + 1] != -1)
		{
			forward++;
			rowTotal += workingRowDiag[forward];
			if(workingRowDiag[forward] == tilePlayed)
			{
				sameNumRow++;
			}
		}
		
		while(workingColDiag[up - 1] != 0 && workingColDiag[up - 1] != -1)
		{
			up--;
			colTotal += workingColDiag[up];
			if(workingColDiag[up] == tilePlayed)
			{
				sameNumCol++;
			}
		}
		while(workingColDiag[down + 1] != 0 && workingColDiag[down + 1] != -1)
		{
			down++;
			colTotal += workingColDiag[down];
			if(workingColDiag[down] == tilePlayed)
			{
				sameNumCol++;
			}
		}
		 
		
		// scoring block for everything
		
		if(rowTotal <= 24 && colTotal <= 24) //only score if not bust.
		{
			p_board[row][col] = tilePlayed; //play is legal, so place tile.
			
			//checks the runs ascending or descending.
			runTotalDescCol = testRunsDown(workingColDiag, row); 
			runTotalDescRow = testRunsDown(workingRowDiag, col);
			runTotalAscCol =  testRunsUp(workingColDiag, row);
			runTotalAscRow = testRunsUp(workingRowDiag, col);
			
			if(rowTotal == 24)
			{
				setNoPlayMarkersDR(row, col);
			}
			
			if(colTotal == 24)
			{
				setNoPlayMarkersDC(row, col);
			}
			
			if(rowTotal == 7 && tilePlayed != 7)
			{
				totalRowColScore += 20;
			}
			if(colTotal == 7 && tilePlayed != 7)
			{
				totalRowColScore += 20;
			}
			
			System.out.println("DiagrowTotal is: " + rowTotal);
			//scores if the total in the row is 7 or 24
			switch(rowTotal)
			{
				case 24: totalRowColScore += 40;  break;
			}
			System.out.println("DiagcolTotal is: " + colTotal); 
			switch(colTotal)
			{
				case 24: totalRowColScore += 40;  break;
			}
			
			System.out.println("DiagsameNumRow is: " + sameNumRow);
			//scores 3/4-of-kind
			switch(sameNumRow)
			{
				case 3:  totalRowColScore += 50;  break;
				case 4:  totalRowColScore += 60;  break;
			}
			
			System.out.println("DiagsameNumCol is: " + sameNumCol);
			switch(sameNumCol)
			{
				case 3:  totalRowColScore += 50;  break;
				case 4:  totalRowColScore += 60;  break;
			}
			System.out.println("DiagSum of runTotalDescCol" + runTotalDescCol);
			// scores runs, both descending and ascending
			switch(runTotalDescCol)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
			
			System.out.println("DiagSum of runTotalAscCol is: "  + runTotalAscCol);
			// scores runs, both descending and ascending
			switch(runTotalAscCol)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
			System.out.println("Diag Sum of runTotalDescRow is: " + runTotalDescRow);
			switch(runTotalDescRow)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
			System.out.println("Diag Sum of runTotalAscRow is: " + runTotalAscRow);
			switch(runTotalAscRow)
			{
				case 3:	totalRowColScore += 30;  break;
				case 4: totalRowColScore += 40;  break;
				case 5: totalRowColScore += 50;  break;
				case 6: totalRowColScore += 60;  break;
			}
		}
		
		else if(rowTotal > 24 || colTotal > 24)
		{
			totalRowColScore = -1;
		}
		
		System.out.println("The total for Diag is: " + totalRowColScore);
		return totalRowColScore;
	}
	
	/**
	 * testRunsDown checks for the runs being proper
	 * @param row to be checked
	 * @param where the tile is located
	 * @return int how large a run it is
	 */
	private int testRunsDown(int[] workingArray, int tileLocation)
	{
		int tileAmt = workingArray[tileLocation];
		int downTotal = 0;
		int upTotal = 0;
		int offsetDescending = tileLocation;
		int offsetAscending = tileLocation;
		int mutateDown = 1;
		int mutateUp = 1;
		
		while(workingArray[offsetDescending - 1] != 0 && workingArray[offsetDescending - 1] != -1)
		{
			offsetDescending--;
			if(workingArray[offsetDescending] == tileAmt - mutateDown)
			{
				mutateDown ++;
				downTotal++;
			}
		}
		
		while(workingArray[offsetAscending + 1] != 0 && workingArray[offsetAscending + 1] != -1)
		{
			offsetAscending++;
			if(workingArray[offsetAscending] == tileAmt + mutateUp)
			{
				mutateUp ++;
				upTotal++;
			}
		}
		
		return downTotal + upTotal + 1;
	}
	
	/**
	 * testRunsUp checks for the runs being proper
	 * @param row to be checked
	 * @param where the tile is located
	 * @return int how large a run it is
	 */
	private int testRunsUp(int[] workingArray, int tileLocation)
	{
		int tileAmt = workingArray[tileLocation];
		int downTotal = 0;
		int upTotal = 0;
		int offsetDescending = tileLocation;
		int offsetAscending = tileLocation;
		int mutateDown = 1;
		int mutateUp = 1;
		
		while(workingArray[offsetDescending - 1] != 0 && workingArray[offsetDescending - 1] != -1)
		{
			offsetDescending--;
			if(workingArray[offsetDescending] == tileAmt + mutateDown)
			{
				mutateDown++;
				downTotal++;
			}
		}
		
		while(workingArray[offsetAscending + 1] != 0 && workingArray[offsetAscending + 1] != -1)
		{
			offsetAscending++;
			if(workingArray[offsetAscending] == tileAmt - mutateUp)
			{
				mutateUp ++;
				upTotal++;
			}
		}
		
		return downTotal + upTotal + 1;
	}

	/**
	 * checkDouble checks to see if the tile played is a doubling tile
	 * @param row
	 * @param col
	 * @return true if square played is a double square
	 */
	private boolean checkDouble(int row, int col)
	{
		return (row == 1 && col == 3 
				|| row == 3 && col == 2 
				|| row == 5 && col == 1
				|| row == 6 && col == 3
				|| row == 7 && col == 5
				|| row == 2 && col == 5
				|| row == 5 && col == 6
				|| row == 3 && col == 7);
		
	}
	
	private void setNoPlayMarkersHV(int row, int col)
	{
		int tmpCol = col;
		while(p_board[row][tmpCol] != 0)
		{
			tmpCol--;
		}
		p_board[row][tmpCol] = -1;
		tmpCol = col;
		while(p_board[row][tmpCol] != 0)
		{
			tmpCol++;
		}
		p_board[row][tmpCol] = -1;
	}

	private void setNoPlayMarkersDR(int row, int col)
	{
		int tmpCol = col;
		int tmpRow = row;
		while(p_board[tmpRow][tmpCol] != 0)
		{
			tmpRow--;
			tmpCol--;
		}
		p_board[tmpRow][tmpCol] = -1;
		tmpCol = col;
		tmpRow = row;
		while(p_board[row][tmpCol] != 0)
		{
			tmpRow++;
			tmpCol++;
		}
		p_board[tmpRow][tmpCol] = -1;
	}
	
	private void setNoPlayMarkersDC(int row, int col)
	{
		int tmpCol = col;
		int tmpRow = row;
		while(p_board[tmpRow][tmpCol] != 0)
		{
			tmpRow--;
			tmpCol++;
		}
		p_board[tmpRow][tmpCol] = -1;
		tmpCol = col;
		tmpRow = row;
		while(p_board[row][tmpCol] != 0)
		{
			tmpRow++;
			tmpCol--;
		}
		p_board[tmpRow][tmpCol] = -1;
	}

	public int[][] getBoard()
	{
		return p_board;
	}
}
